﻿namespace GenericHtml
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    public static class MetadataManager
    {
        private static object state = new object();
        private static string PK = "Id";
        private static string Create = "CreateUser";
        private static string Update = "UpdateUser";
        private static string CreationTime = "CreationTime";
        private static string UpdatedTime = "UpdatedTime";

        private static Dictionary<string, DynamicTable> _caches =
            new Dictionary<string, DynamicTable>(StringComparer.OrdinalIgnoreCase);

        private static Dictionary<int, DynamicControl> _controls =
            new Dictionary<int, DynamicControl>();

        public static void Initialize()
        {
            lock (state)
            {
                var controls = GenericConfigure.Provider.GetControls();
                foreach (var control in controls)
                {
                    _controls.Add(control.Id, control);
                }

                var tables = GenericConfigure.Provider.GetAllTables();
                foreach (var item in tables)
                {
                    try
                    {
                        item.Command = CreateCommand(item);
                        _caches.Add(item.Name, item);
                    }
                    catch
                    { 
                    }
                }
            }
        }

        public static void AddTable(DynamicTable table)
        {
            lock (state)
            {
                table.Command = CreateCommand(table);
                _caches.Add(table.Name, table);
            }
        }

        public static void RemoveTable(string name)
        {
            lock (state)
            {
                _caches.Remove(name);
            }
        }

        public static DynamicTable GetTable(string name)
        {
            lock (state)
            {
                DynamicTable table;
                _caches.TryGetValue(name, out table);
                return table;
            }
        }

        public static DynamicControl GetControl(int id)
        {
            return _controls[id];
        }

        public static TableCommand CreateCommand(DynamicTable table)
        {
            TableCommand cmd = new TableCommand();
            SqlBuilder sql = new MSSqlBuilder();
            var columns = table.Columns.Where(k => !k.IsSystemDefault)
                               .Select(k => k.Name).ToArray();

            cmd.InsertCommand =
                sql.InsertInto(
                        table.Name,
                        columns.Union(new string[] { Create, Update }).ToArray())
                   .Values(columns.Union(new string[] { Create, Update }).Select(k => "@" + k).ToArray())
                   .ToString();

            sql.Clear();
            cmd.UpdateCommand =
                sql.Update(table.Name)
                   .Set(columns.Union(new string[] { Update }).Select(k => k + "= @" + k).ToArray())
                   .Set(UpdatedTime + " = GETDATE()")
                   .Where(PK + " = " + "@" + PK)
                   .ToString();

            sql.Clear();
            cmd.DeleteCommand =
                sql.Delete(table.Name)
                   .Where(PK + " = " + "@" + PK)
                   .ToString();

            sql.Clear();
            sql.Select("ROW_NUMBER() OVER(ORDER BY t1.Id) __RowId");
            sql.Select("t1." + PK);
            sql.Select(columns.Union(new string[] { Create, Update, CreationTime, UpdatedTime })
                              .Select(k => "t1." + k).ToArray());
            sql.Select("t2.U_CName AS CreateName");
            sql.Select("t3.U_CName AS UpdatedName");
            sql.From(table.Name + " AS t1")
               .InnerJoin("sys_UserInfo AS t2")
               .On("t1." + Create + " = t2.U_ID")
               .InnerJoin("sys_UserInfo AS t3")
               .On("t1." + Update + " = t3.U_ID");

            cmd.SelectCommand = sql.ToString();

            return cmd;
        }
    }
}
